#include "main.h"

// for key scanning
uint32_t cnt1;
uint32_t show_save;
uint32_t temp_set_save;
uint8_t set_cnt, up_cnt, down_cnt;
uint8_t pinNow;
bool pinSet_now, pinUp_now, pinDown_now;
bool pinSet_last, pinUp_last, pinDown_last;
bool set_long = FALSE;
bool set_short = FALSE;
bool up_short = FALSE;
bool down_short = FALSE;

void key_init()
{
	GPIO_Init(KEY_PORT, KEY_SET|KEY_UP|KEY_DOWN, GPIO_MODE_IN_FL_IT);
	EXTI_SetExtIntSensitivity(EXTI_PORT_GPIOC, EXTI_SENSITIVITY_FALL_ONLY);

	cnt1 = 0;
	pinNow = 0;
	set_cnt = 0;
	up_cnt = 0;
	down_cnt = 0;

	set_long = FALSE;
	set_short = FALSE;
	up_short = FALSE;
	down_short = FALSE;

	mode = MODE_INIT;
}

void key_scan(void)
{

	pinNow = 0xFF - GPIO_ReadInputData(KEY_PORT);
	pinSet_now  = pinNow & KEY_SET;
	pinUp_now   = pinNow & KEY_UP;
	pinDown_now = pinNow & KEY_DOWN;

//////////////////////////////////////////////////////////////

	if (pinSet_now & pinSet_last) {
		if (!set_long)
			set_cnt++;
		if (set_cnt>LONG_PRESS) {
			set_long = TRUE;
			set_cnt = 0;
		}
	}else {
		if (set_cnt>SHORT_PRESS) {
			set_short = TRUE;
			set_cnt = 0;
		}else{
			if (set_long)
				set_long = FALSE;
			set_cnt = 0;
		}
	}
	
	if (pinUp_now & pinUp_last) {
		up_cnt++;
		if (up_cnt>MID_PRESS) {
			up_short = TRUE;
			up_cnt = up_cnt - REPEAT_PRESS;
		}
	}else{
		if (up_cnt>SHORT_PRESS) {
			up_short = TRUE;
			up_cnt = 0;
		}
	}

	if (pinDown_now & pinDown_last) {
		down_cnt++;
		if (down_cnt>MID_PRESS) {
			down_short = TRUE;
			down_cnt = down_cnt - REPEAT_PRESS;
		}
	}else{
		if (down_cnt>SHORT_PRESS) {
			down_short = TRUE;
			down_cnt = 0;
		}
	}

//////////////////////////////////////////////////////////////

	// auto quit setting mode in 5 seconds without any key press
	if (up_short | down_short | set_short | set_long)
		cnt1=0;

	if (mode) {
		if (cnt1>250) {
			mode = MODE_INIT;
			show_value = show_save;
			save_parameter();
			cnt1 = 0;
			TIM2_Cmd(ENABLE);
		}else{
			if (mode!=MODE_SHUTDOWN)
				cnt1++;
		}
	}

	switch (mode) {

		case MODE_OFFSET_SET:
			show_value = temp_offset;
			if (offset_positive) {
				if (up_short) {
					if (temp_offset<99)
						temp_offset++;
					up_short = FALSE;
				}else if (down_short) {
					if (temp_offset==0){
						temp_offset = 1;
						offset_positive = FALSE;
					}else if (temp_offset>0)
						temp_offset--;
					down_short = FALSE;
				}
			}else {
				if (up_short) {
					if (temp_offset>0)
						temp_offset--;
					if (temp_offset==0)
						offset_positive = TRUE;
					up_short = FALSE;
				}else if (down_short) {
					if (temp_offset<99)
						temp_offset++;
					down_short = FALSE;
				}
			}
			break;

		case MODE_PID_SET:
			show_value = temp_pid;
			if (up_short) {
				if (temp_pid<999)
					temp_pid++;
				up_short = FALSE;
			}else if (down_short) {
				if (temp_pid>2)
					temp_pid--;
				down_short = FALSE;
			}
			break;

		case MODE_TI_SET:
			show_value = temp_shutdown;
			if (up_short) {
				if (temp_shutdown<999)
					temp_shutdown++;
				up_short = FALSE;
			}else if (down_short) {
				if (temp_shutdown>0)
					temp_shutdown--;
				down_short = FALSE;
			}
			break;

		case MODE_ALERT_SET:
			show_value = temp_alert;
			if (up_short) {
				if (temp_alert<99)
					temp_alert++;
				up_short = FALSE;
			}else if (down_short) {
				if (temp_alert>0)
					temp_alert--;
				down_short = FALSE;
			}
			break;

		case MODE_PWM_SET:
			show_value = temp_pwm;
			if (up_short) {
				if (temp_pwm<99)
					temp_pwm++;
				up_short = FALSE;
			}else if (down_short) {
				if (temp_pwm>0)
					temp_pwm--;
				down_short = FALSE;
			}
			break;

		case MODE_SET_TEMP:
			show_value = temp_set;
			if (up_short) {
				if (temp_set<TEMP_LIMITED){
					temp_set++;
				}
				up_short = FALSE;
			}else if (down_short) {
				if (temp_set>0) {
					temp_set--;
				}
				down_short = FALSE;
			}
			break;

		case MODE_LOCK_SET:
			show_value = temp_lock;
			if (up_short) {
				if (temp_lock<99){
					temp_lock++;
				}
				up_short = FALSE;
			}else if (down_short) {
				if (temp_lock>0) {
					temp_lock--;
				}
				down_short = FALSE;
			}
			break;

	}

	// 长按set键进入设置模式
	if (set_long) {

		switch(mode) {
			case MODE_INIT:
				mode = MODE_OFFSET_BEGIN;
				show_save = show_value;
				TIM2_Cmd(DISABLE);
				break;
			case MODE_PID_BEGIN:
				mode = MODE_DEFAULT;
				load_default_parameter();
				break;
			default:
				break;
		}
		//set_long = FALSE;

	}else if (set_short) {

		switch(mode){

			case MODE_INIT:     
				mode = MODE_SET_TEMP;
				show_save = show_value;
				temp_set_save = temp_set;
				GPIO_WriteHigh(HEAT_PORT, HEAT);
				GPIO_WriteHigh(LED_PORT, LED_STATUS);
				cnt1 = 0; 
				TIM2_Cmd(DISABLE);
				break;

			case MODE_OFFSET_BEGIN:
				mode = MODE_OFFSET_SET;
				GPIO_WriteHigh(HEAT_PORT, HEAT);
				GPIO_WriteHigh(LED_PORT, LED_STATUS);
				cnt1 = 0;
				break;

			case MODE_OFFSET_SET:
				mode = MODE_PID_BEGIN;      
				cnt1 = 0; 
				break;

			case MODE_PID_BEGIN:
				mode = MODE_PID_SET;
				cnt1 = 0;
				break;

			case MODE_PID_SET:
				mode = MODE_ALERT_BEGIN;
				cnt1 = 0;
				break;

			case MODE_ALERT_BEGIN:
				mode = MODE_ALERT_SET;
				cnt1 = 0;
				break;

			case MODE_ALERT_SET:
				mode = MODE_PWM_BEGIN;
				cnt1 = 0;
				break;

			case MODE_PWM_BEGIN:
				mode = MODE_PWM_SET;
				cnt1 = 0 ;
				break;

			case MODE_PWM_SET:
				mode = MODE_LOCK_BEGIN;
				cnt1 = 0;
				break;

			case MODE_LOCK_BEGIN:
				cnt1 = 0;
				mode = MODE_LOCK_SET;
				break;

			case MODE_LOCK_SET:
				cnt1 = 0 ;
				mode = MODE_TI_BEGIN;
				break;

			case MODE_TI_BEGIN:
				mode = MODE_TI_SET;
				cnt1 = 0;
				break;

			case MODE_TI_SET:
				mode = MODE_INIT;
				show_value = show_save;
				PIDInit(&sPID, temp_pid, 0, 0, temp_set);
				cnt1 = 0;
				save_parameter(); 
				TIM2_Cmd(ENABLE);
				if (temp_set!=temp_set_save) {
					lock = FALSE;
					real_lock = FALSE;
				}
				break; 

			case MODE_DEFAULT:
			case MODE_SHUTDOWN:
			case MODE_SET_TEMP:	
				mode = MODE_INIT; 
				show_value = show_save;
				PIDInit(&sPID, temp_pid, 0, 0, temp_set);
				save_set_temp();
				TIM2_Cmd(ENABLE);
				cnt1 = 0;
				if (temp_set!=temp_set_save) {
					lock = FALSE;
					real_lock = FALSE;
				}
				break;

			default: 
				break;
		}
		set_short = FALSE;
	}

	pinSet_last = pinSet_now;
	pinUp_last = pinUp_now;
	pinDown_last = pinDown_now;

}